/*
 * Bare API methods have no local side effects (unless you count debouncing).
 */

import { Credentials, KeratinError, OcrError } from './types';
import { get, post, del, postJson } from './verbs';

// TODO: extract debouncing
let inflight: boolean = false;

let ISSUER: string = '';

export function setHost(URL: string): void {
    ISSUER = URL.replace(/\/$/, '');
}

interface TokenResponse {
    id_token: string;
}
interface CredentialsSeccode {
    [index: string]: string;
    phone: string;
}
interface SeccodeResponse {
    ttl: number;
}
// 重置密码
export function resetPassword(credentials: Credentials): Promise < string > {
    return new Promise((fulfill: (data?: string) => any, reject: (errors : OcrError) => any) => {
        if (inflight) {
            /*eslint-disable */
            reject({message: '重置中……'});
            /*eslint-enable */
        } else {
            inflight = true;
        }

        post < TokenResponse >(url('/users/reset'), credentials).then((result) => {
            inflight = false;
            fulfill(result && result.id_token
                ? result.id_token
                : '');
        }, (error) => {
            inflight = false;
            reject(error);
        });
    });
}
export function signup(credentials: Credentials): Promise < any > {
    return new Promise((fulfill: (data?: any) => any, reject: (errors : OcrError) => any) => {
        if (inflight) {
            /*eslint-disable */
            reject({message: '注册中……'});
            /*eslint-enable */
        } else {
            inflight = true;
        }

        post < any >(url('/users'), credentials).then(() => {
            inflight = false;
            fulfill({ response: 'success' });
        }, (error) => {
            inflight = false;
            reject(error);
        });
    });
}
// 获取用户信息
export function getUser(): Promise < any > {
    return get < any >(url('/users'), {})
        .then(response => ({ response }))
        .catch(error => ({ error }));
}
function isTaken(e: OcrError | KeratinError) {
    return e.field === 'username' && e.message === 'TAKEN';
}

export function isAvailable(username: string): Promise < boolean > {
    return get < boolean >(url('/accounts/available'), { username }).then((bool) => bool).catch((e: Error | KeratinError[]) => {
        if (!(e instanceof Error) && e.some(isTaken)) {
            return false;
        }
        throw e;
    });
}

export function refresh(): Promise < string > {
    return get < TokenResponse >(url('/session/refresh'), {}).then((result) => result.id_token);
}

export function login(credentials: Credentials): Promise < string > {
    return post < TokenResponse >(url('/session/login'), credentials).then((result) => result.id_token);
}
// 获取短信验证码
export function seccode(credentialsSeccode: CredentialsSeccode): Promise < number > {
    return post < SeccodeResponse >(url('/seccode'), credentialsSeccode).then((result) => result.ttl);
}
// 验证码登录
export function loginSeccode(credentials: Credentials): Promise < string > {
    return post < TokenResponse >(url('/session/login/seccode'), credentials).then((result) => (result.id_token));
}
// 提交用户个人信息
export function identify(args: any): Promise < string > {
    return postJson < any >(url('/users/identify'), args);
}
export function logout(): Promise < void > {
    return del < void >(url('/session'));
}

export function requestPasswordReset(username: string): Promise < {} > {
    return get(url('/password/reset'), { username });
}

export function changePassword(args: {
oldPwd: string,
newPwd: string
}): Promise < string > {
    return post < string >(url('/users/changePwd'), args);
}

function url(path: string): string {
    if (!ISSUER.length) {
        throw new Error('ISSUER not set');
    }
    return `${ISSUER}${path}`;
}
